﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AutoMapper;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using seejee_Backendium.Core.Dtos;
using seejee_Backendium.Core.Interfaces;
using seejee_Backendium.Core.Models;
using seejee_Backendium.Data.DbContest;

namespace seejee_Backendium.Data.Services
{
    public class MenuService : IMenuService
    {
        private readonly ApplicationDbContext _context;
        private readonly ILogger<MenuService> _logger;
        private readonly IMapper _mapper;

        public MenuService(ApplicationDbContext context, ILogger<MenuService> logger, IMapper mapper)
        {
            _context = context;
            _logger = logger;
            _mapper = mapper;
        }

        public async Task<IEnumerable<MenuDto>> GetAllMenusAsync()
        {
            try
            {
                var menus = await _context.Menus
                    .AsNoTracking()
                    .Include(m => m.Children)
                    .Include(m => m.Parent)
                    .Where(m => m.IsActive)
                    .OrderBy(m => m.Sort)
                    .Select(m => new MenuDto
                    {
                        Id = m.Id,
                        ParentId = m.ParentId,
                        Title = m.Title ?? string.Empty,
                        Icon = m.Icon ?? string.Empty,
                        Index = m.Index ?? string.Empty,
                        RoutePath = m.RoutePath ?? string.Empty,
                        GroupName = m.GroupName ?? string.Empty,
                        Sort = m.Sort,
                        IsActive = m.IsActive,
                        ParentTitle = m.Parent != null ? m.Parent.Title : string.Empty,
                        Children = m.Children.Select(c => new MenuDto
                        {
                            // 映射子菜单属性，同样处理NULL值
                            Id = c.Id,
                            Title = c.Title ?? string.Empty,
                            // 其他属性...
                        }).ToList()
                    })
                    .ToListAsync();

                return menus.Where(m => m.ParentId == null).ToList();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取所有菜单时发生错误");
                throw new ApplicationException("获取菜单列表失败，请稍后重试", ex);
            }
        }

        public async Task<MenuDto> GetMenuByIdAsync(int id)
        {
            if (id <= 0) throw new ArgumentException("菜单ID必须大于0");

            try
            {
                var menu = await _context.Menus
                    .AsNoTracking()
                    .Include(m => m.Children)
                    .Include(m => m.Parent)
                    .FirstOrDefaultAsync(m => m.Id == id);

                return menu == null
                    ? throw new KeyNotFoundException($"未找到ID为 {id} 的菜单")
                    : _mapper.Map<MenuDto>(menu);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"获取ID为 {id} 的菜单时发生错误");
                throw;
            }
        }

        public async Task<MenuDto> CreateMenuAsync(MenuDto menuDto)
        {
            if (menuDto == null) throw new ArgumentNullException(nameof(menuDto));

            try
            {
                if (await _context.Menus.AnyAsync(m => m.Index == menuDto.Index))
                    throw new InvalidOperationException($"菜单索引 '{menuDto.Index}' 已存在");

                if (menuDto.ParentId.HasValue && !await _context.Menus.AnyAsync(m => m.Id == menuDto.ParentId.Value))
                    throw new InvalidOperationException($"父菜单ID {menuDto.ParentId} 不存在");

                var menu = _mapper.Map<Menu>(menuDto);
                await _context.Menus.AddAsync(menu);
                await _context.SaveChangesAsync();

                return await GetMenuByIdAsync(menu.Id);
            }
            catch (DbUpdateException ex)
            {
                _logger.LogError(ex, "创建菜单时数据库错误");
                throw new ApplicationException("创建菜单失败，请检查数据是否正确", ex);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "创建菜单时发生错误");
                throw;
            }
        }

        public async Task UpdateMenuAsync(int id, MenuDto menuDto)
        {
            if (id <= 0) throw new ArgumentException("菜单ID必须大于0");
            if (menuDto == null) throw new ArgumentNullException(nameof(menuDto));
            if (id != menuDto.Id) throw new ArgumentException("菜单ID不匹配");

            try
            {
                var existingMenu = await _context.Menus.FindAsync(id)
                    ?? throw new KeyNotFoundException($"未找到ID为 {id} 的菜单");

                if (existingMenu.Index != menuDto.Index &&
                    await _context.Menus.AnyAsync(m => m.Index == menuDto.Index && m.Id != id))
                    throw new InvalidOperationException($"菜单索引 '{menuDto.Index}' 已被使用");

                if (menuDto.ParentId.HasValue)
                {
                    if (menuDto.ParentId.Value == id)
                        throw new InvalidOperationException("菜单不能设置自己为父菜单");

                    if (!await _context.Menus.AnyAsync(m => m.Id == menuDto.ParentId.Value))
                        throw new InvalidOperationException($"父菜单ID {menuDto.ParentId} 不存在");
                }

                _mapper.Map(menuDto, existingMenu);
                _context.Menus.Update(existingMenu);
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateException ex)
            {
                _logger.LogError(ex, $"更新ID为 {id} 的菜单时数据库错误");
                throw new ApplicationException("更新菜单失败，请检查数据是否正确", ex);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"更新ID为 {id} 的菜单时发生错误");
                throw;
            }
        }

        public async Task DeleteMenuAsync(int id)
        {
            if (id <= 0) throw new ArgumentException("菜单ID必须大于0");

            try
            {
                using var transaction = await _context.Database.BeginTransactionAsync();
                try
                {
                    await DeleteChildrenRecursive(id);
                    var menu = await _context.Menus.FindAsync(id)
                        ?? throw new KeyNotFoundException($"未找到ID为 {id} 的菜单");

                    _context.Menus.Remove(menu);
                    await _context.SaveChangesAsync();
                    await transaction.CommitAsync();
                }
                catch
                {
                    await transaction.RollbackAsync();
                    throw;
                }
            }
            catch (DbUpdateException ex)
            {
                _logger.LogError(ex, $"删除ID为 {id} 的菜单时数据库错误");
                throw new ApplicationException("删除菜单失败，请稍后重试", ex);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"删除ID为 {id} 的菜单时发生错误");
                throw;
            }
        }

        private async Task DeleteChildrenRecursive(int parentId)
        {
            var children = await _context.Menus
                .Where(m => m.ParentId == parentId)
                .ToListAsync();

            foreach (var child in children)
            {
                await DeleteChildrenRecursive(child.Id);
                _context.Menus.Remove(child);
            }
            await _context.SaveChangesAsync();
        }
    }
}